/**
 * 
 */
package com.naveejr.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.ResourceBundle;

import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

import org.primefaces.component.inputtext.InputText;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.naveejr.dao.UserDao;
import com.naveejr.domain.UserEntity;
import com.naveejr.services.UserService;

/**
 * @author rajeevan
 *
 */
public class UserServiceImpl implements UserService, UserDetailsService {

	private static final String USER_AVAILABLE_MSG = "userAvailableMsg";
	private static final String ROLE_USER = "ROLE_USER";
	private static final String BAD_CREDENTIALS = "badCredentials";
	private static final String FAIL_TO_ADD_TO_DATABASE_STRING = "failToAddToDatabaseString";
	private static final String USER_EXISTS_MSG = "userExistsMsg";
	private static final String MESSAGE_LABELS = "message-labels";

	private UserDao userDao;

	protected FacesMessage constructErrorMessages(Severity severity, String message, String details) {
		return new FacesMessage(severity, message, details);
	}

	protected ResourceBundle getMessageBundle() {
		return ResourceBundle.getBundle(MESSAGE_LABELS);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.naveejr.services.UserService#createUser(com.naveejr.domain.UserEntity
	 * )
	 */
	public boolean createUser(UserEntity user) {
		if (!userDao.checkAvailable(user.getUserName())) {
			FacesMessage message = constructErrorMessages(FacesMessage.SEVERITY_ERROR,
					String.format(getMessageBundle().getString(USER_EXISTS_MSG), user.getUserName()), null);

			FacesContext.getCurrentInstance().addMessage(null, message);

			return false;
		}
		try {
			userDao.save(user);

		} catch (Exception e) {
			FacesMessage message = constructErrorMessages(FacesMessage.SEVERITY_ERROR,
					String.format(getMessageBundle().getString(FAIL_TO_ADD_TO_DATABASE_STRING), user.getUserName()), e.getMessage());
			FacesContext.getCurrentInstance().addMessage(null, message);
			return false;
		}
		return true;
	}

	public final UserDao getUserDao() {
		return userDao;
	}

	public final void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.core.userdetails.UserDetailsService#
	 * loadUserByUsername(java.lang.String)
	 */
	public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
		UserEntity user = userDao.loadUserByUserName(userName);

		if (user == null) {
			throw new UsernameNotFoundException(String.format(getMessageBundle().getString(BAD_CREDENTIALS), userName));
		}

		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		authorities.add(new SimpleGrantedAuthority(ROLE_USER));

		User userDetails = new User(user.getUserName(), user.getPassword(), authorities);
		return userDetails;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.naveejr.services.UserService#checkAvailable(javax.faces.event.
	 * AjaxBehaviorEvent)
	 */
	public boolean checkAvailable(AjaxBehaviorEvent event) {
		InputText userNameInputText = (InputText) event.getSource();
		String userName = (String) userNameInputText.getValue();
		boolean available = userDao.checkAvailable(userName);
		FacesMessage message;
		if (!available) {
			message = constructErrorMessages(FacesMessage.SEVERITY_ERROR, String.format(getMessageBundle().getString(USER_EXISTS_MSG), userName), null);
		} else {
			message = constructErrorMessages(FacesMessage.SEVERITY_INFO, String.format(getMessageBundle().getString(USER_AVAILABLE_MSG), userName), null

			);
		}

		FacesContext.getCurrentInstance().addMessage(event.getComponent().getClientId(), message);
		return available;
	}
}
